﻿using Newtonsoft.Json;

using NPOI.XWPF.UserModel;

using PLCS.Domain.Logs;
using PLCS.Domain.Shared.Logs;

using RestSharp;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Repositories;
using PLCS.Shared.Common.Helper;

namespace PLCS.SocialHttpClient
{
    public class ApiRequestService : ITransientDependency
    {
        private readonly IRepository<InterfaceLog, Guid> _repository;

        public ApiRequestService(IRepository<InterfaceLog, Guid> repository)
        {
            _repository = repository;
        }

        public async Task<T> SendWebApiRequest<T>(string url, HttpMethod method, string reponseSide, string interFaceName, string interfaceDescription, object data = null, int retryCount = 3) where T : class, new()
        {
            using (var client = new HttpClient())
            {
                // 将对象转换为HttpContent
                HttpContent content = null;
                string json = "{}";

                if (data != null)
                {
                    json = JsonConvert.SerializeObject(data);
                    content = new StringContent(json, Encoding.UTF8, "application/json");
                }

                int currentRetry = 0;
                while (currentRetry < retryCount)
                {
                    try
                    {
                        HttpRequestMessage request = new HttpRequestMessage(method, url);
                        if (content != null)
                        {
                            request.Content = content;
                        }
                        var response = await client.SendAsync(request);
                        response.EnsureSuccessStatusCode();
                        var responseText = await response.Content.ReadAsStringAsync();

                        var responseInfo = new InterfaceLog("PLCS", reponseSide, interFaceName, interfaceDescription ?? string.Empty, InterfaceMode.WebApi, InterfaceDataType.Json, json, responseText);
                        await _repository.InsertAsync(responseInfo);
                        return JsonConvert.DeserializeObject<T>(responseText);
                    }
                    catch (HttpRequestException ex)
                    {
                        currentRetry++;
                        if (currentRetry == retryCount)
                        {
                            string reponseJson = JsonConvert.SerializeObject(new { message = ex.Message });
                            var responseInfo = new InterfaceLog("PLCS", reponseSide, interFaceName, interfaceDescription ?? string.Empty, InterfaceMode.WebApi, InterfaceDataType.Json, json, reponseJson);
                            await _repository.InsertAsync(responseInfo);
                        }
                        await Task.Delay(1000);
                    }
                }
                throw new Exception($"Failed to execute HTTP {method} request to {url} after {retryCount} attempts");
            }
        }

        public async Task<string> SendWebApiRequest(string url, HttpMethod method, string reponseSide, string interFaceName, string interfaceDescription, object data = null, int retryCount = 3)
        {
            using (var client = new HttpClient())
            {
                // 将对象转换为HttpContent
                HttpContent content = null;
                string json = "{}";
                if (data != null)
                {
                    json = JsonConvert.SerializeObject(data);

                    content = new StringContent(json, Encoding.UTF8, "application/json");
                }

                int currentRetry = 0;
                while (currentRetry < retryCount)
                {
                    try
                    {
                        HttpRequestMessage request = new HttpRequestMessage(method, url);
                        if (content != null)
                        {
                            request.Content = content;
                        }
                        var response = await client.SendAsync(request);
                        response.EnsureSuccessStatusCode();
                        var responseText = await response.Content.ReadAsStringAsync();

                        var responseInfo = new InterfaceLog("PLCS", reponseSide, interFaceName, interfaceDescription ?? string.Empty, InterfaceMode.WebApi, InterfaceDataType.Json, json, responseText);
                        await _repository.InsertAsync(responseInfo);
                        return responseText;
                    }
                    catch (HttpRequestException ex)
                    {
                        currentRetry++;
                        if (currentRetry == retryCount)
                        {
                            string reponseJson = JsonConvert.SerializeObject(new { message = ex.Message });
                            var responseInfo = new InterfaceLog("PLCS", reponseSide, interFaceName, interfaceDescription ?? string.Empty, InterfaceMode.WebApi, InterfaceDataType.Json, json, reponseJson);
                            await _repository.InsertAsync(responseInfo);
                        }
                        await Task.Delay(1000);
                    }
                }
                throw new Exception($"Failed to execute HTTP {method} request to {url} after {retryCount} attempts");
            }
        }

        public async Task<string?> SendWebServiceRequest(string url, string reponseSide, string interFaceName, string interfaceDescription, string data = null, int retryCount = 3)
        {
            int currentRetry = 0;
            while (currentRetry < retryCount)
            {
                try
                {
                    using var client = new RestClient();
                    var request = new RestRequest(new Uri(url), Method.Post);
                    request.AddHeader("Content-Type", "text/xml; charset=utf-8");
                    if (data != null)
                    {
                        request.AddParameter("text/xml", data, ParameterType.RequestBody);
                    }
                    var response = await client.ExecuteAsync(request);

                    var responseText = response.Content;

                    var responseInfo = new InterfaceLog("PLCS", reponseSide, interFaceName, interfaceDescription ?? string.Empty, InterfaceMode.WebService, InterfaceDataType.Xml, data ?? string.Empty, responseText);
                    await _repository.InsertAsync(responseInfo);
                    return responseText;
                }
                catch (Exception ex)
                {
                    currentRetry++;
                    if (currentRetry == retryCount)
                    {
                        string reponsexml = XMLHelper.SerializeToXml(new { message = ex.Message });
                        var responseInfo = new InterfaceLog("PLCS", reponseSide, interFaceName, interfaceDescription ?? string.Empty, InterfaceMode.WebApi, InterfaceDataType.Json, data ?? string.Empty, reponsexml);
                        await _repository.InsertAsync(responseInfo);
                    }
                    await Task.Delay(1000);
                }
            }
            throw new Exception($"Failed to execute WebService request to {url} after {retryCount} attempts");
        }
    }
}